package com.cheer.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cheer.dao.ActivityDao;
import com.cheer.dto.ActivityToLeadExcelDTO;
import com.cheer.entity.ActivityEntity;
import com.cheer.entity.OaActivityPartiEntity;
import com.cheer.entity.OaLearnClassEntity;
import com.cheer.entity.OaUserEntity;
import com.cheer.enums.ActivityStatusEnum;
import com.cheer.enums.ActivityTypeEnum;
import com.cheer.exception.ServiceException;
import com.cheer.param.ActivityAchieveUpParam;
import com.cheer.param.ActivityAddOrUpParam;
import com.cheer.param.ActivityPageParam;
import com.cheer.service.OaActivityPartiService;
import com.cheer.service.OaActivityService;
import com.cheer.service.OaLearnClassService;
import com.cheer.service.OaUserService;
import com.cheer.utils.BeanUtil;
import com.cheer.vo.ActivityAchieveVO;
import com.cheer.vo.ActivityInfoVO;
import com.cheer.vo.ActivityPageVO;
import com.cheer.vo.ImgVO;
import org.assertj.core.util.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ActivityServiceImpl extends ServiceImpl<ActivityDao, ActivityEntity> implements OaActivityService {

    @Autowired
    private OaActivityPartiService oaActivityPartiService;

    @Autowired
    private OaLearnClassService oaLearnClassService;

    @Autowired
    private OaUserService oaUserService;

    private static final String SYS_CHANNEL = "系统";
    private static final String SYS_TO_LEAD = "导入";
    /**
     * 活动图片路径位置
     */
    @Value("${activity.dir}")
    private String imageDir;
    /**
     * 活动图片URL前缀
     */
    @Value("${activity.url}")
    private String imageUrlPrefix;


    @Override
    public void add(ActivityAddOrUpParam activityAddOrUpParam) {
        ActivityEntity activityEntity = getActivityEntity(activityAddOrUpParam);
        save(activityEntity);
    }

    private ActivityEntity getActivityEntity(ActivityAddOrUpParam activityAddOrUpParam) {

        // 打卡参数校验
        if( activityAddOrUpParam.getType().equals(ActivityTypeEnum.CHECK.getCode()) ){

            if(Objects.isNull(activityAddOrUpParam.getStartTime())){
                throw new ServiceException(" 打卡模式下开始时间不能为空！");
            }
            if(Objects.isNull(activityAddOrUpParam.getEndTime())){
                throw new ServiceException(" 打卡模式下结束时间不能为空！");
            }
            if(activityAddOrUpParam.getStartTime().getTime()  > activityAddOrUpParam.getEndTime().getTime()){
                throw new ServiceException(" 结束时间不得早于开始时间！");
            }
            if( StrUtil.isBlank(activityAddOrUpParam.getLocationLatitude())
                    || StrUtil.isBlank(activityAddOrUpParam.getLocationLongitude()) ){
                throw new ServiceException(" 打卡模式下打卡位置不能为空！");
            }
            if( StrUtil.isBlank(activityAddOrUpParam.getNotes())){
                throw new ServiceException(" 打卡模式下注意事项不能为空！");
            }
        }
        // 图文打卡
        if( activityAddOrUpParam.getType().equals(ActivityTypeEnum.IMAGE_TEXT.getCode()) ){
            if(CollectionUtil.isEmpty(activityAddOrUpParam.getAchieveImage())){
                throw new ServiceException(" 图文模式下成果展示图不能为空！");
            }
            if(StrUtil.isBlank(activityAddOrUpParam.getAchieveText())){
                throw new ServiceException(" 图文模式下成果展示文字不能为空！");
            }
        }
        ActivityEntity activityEntity = BeanUtil.transform(ActivityEntity.class, activityAddOrUpParam);
        settingDateTime(activityAddOrUpParam, activityEntity);
        activityEntity.setAddTime(System.currentTimeMillis()/1000);
        activityEntity.setAchieveText(activityAddOrUpParam.getAchieveText());
        activityEntity.setAchieveImage(activityAddOrUpParam.getAchieveImageStr());
        // 活动限制
        if(activityAddOrUpParam.getOrgLimit()){
            if(activityAddOrUpParam.getPid() == null){
                throw new ServiceException("未查询到当前指定机构");
            }else{
                Integer pid = activityAddOrUpParam.getPid();
                String path = oaLearnClassService.getOrgPathByPid(pid);
                activityEntity.setOrgPath(path);
            }
        }
        activityEntity.setThumbnail(activityAddOrUpParam.getThumbnail().get(0).getName());
        activityEntity.setImages(activityAddOrUpParam.getImages().get(0).getName());
        return activityEntity;
    }


    @Override
    public IPage<ActivityPageVO> page(ActivityPageParam activityPageParam) {

        IPage<ActivityEntity> page = new Page<>(activityPageParam.getPageNum(), activityPageParam.getPageSize());
        QueryWrapper<ActivityEntity> qw = new QueryWrapper<ActivityEntity>();
        qw.lambda().select(ActivityEntity::getId,
                ActivityEntity::getTitle,
                ActivityEntity::getType,
                ActivityEntity::getIsPublish,
                ActivityEntity::getStartTime,
                ActivityEntity::getEndTime);
        // 开始时间
        if(activityPageParam.getStartTime() != null){
            qw.lambda().ge( ActivityEntity::getStartTime, activityPageParam.getStartTime().getTime()/1000);
        }
        // 结束时间
        if(activityPageParam.getEndTime() != null){
            qw.lambda().le( ActivityEntity::getEndTime, activityPageParam.getEndTime().getTime()/1000);
        }
        // 机构相似度
        if(activityPageParam.getPid() != null){
            String orgPath = oaLearnClassService.getOrgPathByPid(activityPageParam.getPid());
            qw.lambda().likeRight( ActivityEntity::getOrgPath, orgPath);
        }
        page = page(page, qw);
        // 转换page
        return  page.convert( activityEntity -> {
            ActivityPageVO pageVO = new ActivityPageVO();
            pageVO.setTitle(activityEntity.getTitle());
            // 开始日期
            String startTime = DateUtil.format(new Date( activityEntity.getStartTime() * 1000 ), DatePattern.CHINESE_DATE_PATTERN);
            String endTime = DateUtil.format(new Date( activityEntity.getEndTime() * 1000 ), DatePattern.CHINESE_DATE_PATTERN);
            pageVO.setTime(startTime+" ~ "+endTime);
            pageVO.setType(ActivityTypeEnum.getEnumByCode(activityEntity.getType()).getMessage());
            pageVO.setId(activityEntity.getId());
            pageVO.setIsPublish(activityEntity.getIsPublish());
            pageVO.setParticipant(oaActivityPartiService.getParticipant(activityEntity.getId()));
            pageVO.setStatus(ActivityStatusEnum.getStatus(activityEntity.getStartTime(), activityEntity.getEndTime()).getMessage());
            return pageVO;
        });
    }

    @Override
    public void update(ActivityAddOrUpParam activityAddOrUpParam) {

        if(activityAddOrUpParam.getId() == null){
            throw new ServiceException("未获取到当前要修改的记录！");
        }
        ActivityEntity activityEntity = getActivityEntity(activityAddOrUpParam);
        updateById(activityEntity);
    }

    @Override
    public void achievementUpdate(ActivityAchieveUpParam achieve) {

        ActivityEntity activityEntity = getById(achieve.getId());
        if(activityEntity == null){
            throw new ServiceException("未查询到当前记录！");
        }
        activityEntity.setAchieveText(achieve.getAchieveText());
        activityEntity.setAchieveImage(achieve.getAchieveImageStr());
        updateById(activityEntity);
    }

    @Override
    public ActivityAchieveVO achievementInfo(Integer id) {
        ActivityEntity activityEntity = getById(id);
        if(activityEntity == null){
            throw new ServiceException("未查询到要查找的记录！");
        }
        ActivityAchieveVO achieveVO = BeanUtil.transform(ActivityAchieveVO.class, activityEntity );
        achieveVO.setAchieveText(activityEntity.getAchieveText());
        List<ImgVO> lists = new ArrayList<>();
        if(StrUtil.isNotBlank(activityEntity.getAchieveImage())){
            List<String> images = JSONUtil.toList(activityEntity.getAchieveImage(), String.class);
            for (String image : images) {
                lists.add(getImageVO(image));
            }
        }
        achieveVO.setAchieveImage(lists);
        return achieveVO;
    }

    @Override
    public ImgVO uploadImage(MultipartFile file) {
        ImgVO imgVO = new ImgVO();
        String fileName = generateUniqueFileName(file.getOriginalFilename());
        Path filePath = Paths.get(imageDir + fileName);
        try {
            Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);
            imgVO.setName(fileName);
            imgVO.setUrl(imageUrlPrefix + fileName);
            return imgVO;
        } catch (IOException e) {
            throw new ServiceException("上传文件失败！");
        }
    }

    @Override
    public List<ImgVO> upImages(MultipartFile[] files) {

        List<ImgVO> list = new ArrayList<>();
        for (int i = 0; i <files.length; i++) {
            MultipartFile file = files[i];
            String fileName = generateUniqueFileName(file.getOriginalFilename());
            Path filePath = Paths.get(imageDir + fileName);
            try {
                Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);
                ImgVO imgVo = new ImgVO();
                imgVo.setName(fileName)
                        .setUrl(imageUrlPrefix + fileName);
                list.add(imgVo);
            } catch (IOException e) {
                throw new ServiceException("上传文件失败！");
            }
        }
        return list;
    }

    @Override
    public void toLead(MultipartFile excel, Integer id) throws IOException {

        // 读取excel进行人员导入
        ExcelReader reader = ExcelUtil.getReader(excel.getInputStream());
        reader.addHeaderAlias("姓名","name");
        reader.addHeaderAlias("手机号","phone");
        List<ActivityToLeadExcelDTO> list = reader.read(1, 2, ActivityToLeadExcelDTO.class);
        if(CollectionUtil.isEmpty(list)){
            throw new ServiceException("未查询到要导入的数据");
        }
        // 检查用户数据规范性
        // 查看当前是否限制人员机构
        ActivityEntity actInfo = getById(id);
        Boolean orgLimit = actInfo.getOrgLimit();
        // 转换为对象
        List<OaActivityPartiEntity> partiEntities = BeanUtil.batchTransform(OaActivityPartiEntity.class, list);
        partiEntities.forEach( oaActivityPartiEntity -> oaActivityPartiEntity.setChannel(SYS_TO_LEAD) );
        // 验证当前人是否符合条件
        for (int i = 0; i < partiEntities.size(); i++) {
            OaActivityPartiEntity partiEntity = partiEntities.get(i);
            String name = partiEntity.getName();
            String phone = partiEntity.getPhone();
            List<OaUserEntity> oaUserEntities = oaUserService.getByUserNameAndPhone(name, phone);
            // 当前用户不唯一
            if(CollectionUtil.isEmpty(oaUserEntities)){
                throw new ServiceException(" 用户名: " + name + " + " + phone + "系统中未查询到当前用户信息！（建议用户修改手机号）");
            }
            // 存在多个相同的用户直接取最后登陆账户的用户
            OaUserEntity oaUserEntity = oaUserEntities.get(0);
            // 查询当前用户是否已经参加了活动
            OaActivityPartiEntity dbRecord = oaActivityPartiService.getByUserIdAndActId(oaUserEntity.getId(), id);
            if(dbRecord != null){
                partiEntity.setId(dbRecord.getId());
            }
            if(orgLimit){
                if(oaUserEntity.getPath()
                        .contains(actInfo.getOrgPath()) == false){
                    throw new ServiceException("系统开启机构限制 当前用户"+name+"未在指定机构下");
                }
            }
            partiEntity.setOrgPath(oaUserEntity.getPath());
            partiEntity.setUserId(oaUserEntity.getId());
            partiEntity.setName(oaUserEntity.getName());
            partiEntity.setActivityId(id);
            partiEntity.setIsRegistered(true);
            partiEntity.setIsCheckedIn(true);
            partiEntity.setChannel("导入");
            partiEntity.setCheckedTime(System.currentTimeMillis()/1000);
        }
        oaActivityPartiService.saveOrUpdateBatch(partiEntities);
    }

    @Override
    public ActivityInfoVO info(Integer id) {

        ActivityEntity act = getById(id);
        if(act == null){
            throw new ServiceException("未查询到当前要查询的信息！");
        }
        // 图片转换
        ActivityInfoVO infoVO = BeanUtil.transform(ActivityInfoVO.class, act);
        infoVO.setImages(Lists.list(getImageVO(act.getImages())));
        infoVO.setThumbnail(Lists.list(getImageVO(act.getThumbnail())));

        if(StrUtil.isNotBlank(act.getOrgPath())){
            List<Integer> collect = Arrays.stream(act.getOrgPath().split(",")).map(Integer::valueOf).collect(Collectors.toList());
            collect.remove(new Integer(0));
            collect.add(act.getPid());
            infoVO.setPath(collect);
        }

        // 判断是否结果展示
        if(StrUtil.isNotBlank(act.getAchieveImage())){
            List<String> list = JSONUtil.toList(act.getAchieveImage(), String.class);
            List<ImgVO> achieveImage = new ArrayList<>();
            for (String imageName : list) {
                achieveImage.add(getImageVO(imageName));
            }
            infoVO.setAchieveImage(achieveImage);
        }
        // 日期转换
        infoVO.setStartTime(com.cheer.utils.DateUtil.convertSecondsToDateTime(act.getStartTime()));
        infoVO.setEndTime(com.cheer.utils.DateUtil.convertSecondsToDateTime(act.getEndTime()));
        infoVO.setPid(0);
        return infoVO;
    }

    @Override
    public void pubOrCancel(Integer id) {
        ActivityEntity act = getById(id);
        act.setIsPublish(!act.getIsPublish());
        updateById(act);
    }


    private String generateUniqueFileName(String originalFileName) {
        String extension = StringUtils.getFilenameExtension(originalFileName);
        return UUID.randomUUID().toString() + "." + extension;
    }

    /**
     * 保存在时间中
     * @param activityEntity
     */
    public void settingDateTime(ActivityAddOrUpParam activityAddOrUpParam, ActivityEntity activityEntity){

        Long startTimeLong = activityAddOrUpParam.getStartTime().getTime()/1000;
        Long endTimeLong = activityAddOrUpParam.getEndTime().getTime()/1000;
        activityEntity.setStartTime(startTimeLong);
        activityEntity.setEndTime(endTimeLong);
    }

    /**
     * 获取图片转换
     * @param imageName
     * @return
     */
    public ImgVO getImageVO(String imageName){
        ImgVO imgVO = new ImgVO();
        imgVO.setName(imageName);
        imgVO.setUrl(imageUrlPrefix + imageName);
        return imgVO;
    }

}
